package com.voole.security.support;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;

/**
 * 用户请求URL 是否符合权限 校验类
 * 
 * CustomSecurityMetadataSource.getAttributes()校验用户请求URL 是否真是存在于 web应用中
 * CustomAccessDecisionManager.decide() 用户请求URL真是存在后，校验用户 是否拥有 请求这个URL的权限
 */
@Service
public class CustomAccessDecisionManager implements org.springframework.security.access.AccessDecisionManager {

	//检查用户是否够权限访问资源
	//参数authentication是从spring的全局缓存SecurityContextHolder中拿到的，里面是用户的权限信息
	//参数object是url
	//参数configAttributes所需的权限
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
		if (configAttributes == null) {
			throw new AccessDeniedException(" 没有权限访问！ ");
		}
		
		Iterator<ConfigAttribute> iterator = configAttributes.iterator();//请求的URL，需要具备的权限。可以是多个，满足一个即可。比如ROLE_ADMIN,ROLE_USER
		while (iterator.hasNext()) {
			ConfigAttribute configAttribute = iterator.next();
			String needPermission = configAttribute.getAttribute();//迭代出一个需要具备的权限，并迭代用户拥有权限进行比对。authentication用户拥有权限，在CustomUserDetailsServiceImpl实现。
			for (GrantedAuthority ga : authentication.getAuthorities()) {
				if (needPermission.equals(ga.getAuthority())) {
					return;
				}
			}
		}
		//注意：执行这里，后台是会抛异常的，但是界面会跳转到所配的access-denied-page页面
		throw new AccessDeniedException(" 没有权限访问！ ");
	}

	public boolean supports(ConfigAttribute arg0) {
		return true;
	}

	public boolean supports(Class<?> arg0) {
		return true;
	}
}
